<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>java nio自带buffer用法</title>
    <style>
        body {
            background-color: #c7edcc
        }
    </style>
</head>
<body>
<pre>
    java nio提供了Buffer类,内部采用字节数组,数据可放在堆内和堆外

    Buffer提供了几个属性用于控制写入和读取
        mark:用于标记和reset
        position:用于写入和读取(netty buffer有readIndex和writeIndex),当写入数据完毕后,调用flip方法,将limit=position,然后positon=0,用于读取
        limit:读取数据的上限,flip会设置该值为posion,rewind不会设置该值
        capacity:容量,初始化时设置,初始化时capacity和limit都等于最大容量

    一般使用方法:
        1.创建一个buffer
        2.往buffer写入数据
        3.调用flip,准备读取,读取
        4.过程中需要重新读取,调用rewind.准备重复读取
        5.clear,buffer状态回到初始化

    在一个buffer上flip两次,将导致limit和position都为0,然后在该buffer上读取(get)导致underflow异常和写入(put)导致overflow异常

    ByteBuffer有一个方法compact(),用于丢弃已经读取的数据,让没有读取的数据再次至于位置0,虽然这样效率地下,但是有些情况必须这么做,
    通过这种方法效率相对来说高些.使用场景:服务器用于接收网络数据的Buffer,当读取一个消息出来后,剩下的数据需要执行以下compact.

    Java Buffer一旦创建,容量不可更改,所以mina,netty实现了自己的动态Buffer.

    直接Buffer:
        当使用非直接Buffer向通道中写入数据时,一般会发生以下操作:
        1.创建一个临时的直接ByteBuffer对象。
        2.将非直接缓冲区的内容复制到临时缓冲中。
        3.使用临时缓冲区执行低层次I/O操作。
        4.临时缓冲区对象离开作用域，并最终成为被回收的无用数据。
        这样会造成效率低下,如果直接缓冲区被缓存,然后直接使用,效率可以得到提高.直接 buffer创建和释放需要执行操作系统调用而且,分配的内存不在
        jvm栈中,且可达性分析垃圾收集对此无用,使用需要注意.
        DirectByteBuffer属于java对象,一般情况下当改对象被回收后,其直接内存会被回收,如果java对象没有被回收则可能直接内存不够使用

</pre>
</body>
</html>